# -*- coding:utf-8 -*-
# author:hp
# datetime:18-6-22 上午10:11
# software: PyCharm

from project import Project
from random import randint

def init(n):
    timeA = 0
    timeB = 0
    projectList = []
    # 初始化作业 及作业列表, 先后顺序排序, 此时开始时间和响应比的值并未做修改
    for i in range(n):
        arrive = randint(timeA, timeB)
        project = Project('进程{}'.format(i + 1), arrive, randint(4, 9))
        timeA = arrive + 3
        timeB = timeA + 3
        projectList.append(project)
    return projectList


def List2Str(lst, init=False):
    string = ''
    if not init: # 不是初始化 则用repr函数
        for item in lst:
            string = string + item.__repr__() + '\n'
    else:
        for item in lst:
            string = string + item.__str__() + '\n'
    return string


def getAvgRunTime(lst):
    runSum = 0  # 总周转时间
    responseRatioSum = 0  # 总带权周转时间
    for item in lst:
        runSum += (item.start + item.workTime - item.arriveTime)
        responseRatioSum += item.getResponseRatio(item.start)
    return round(runSum / len(lst), 2), round(responseRatioSum / len(lst), 2)


def FCFS(projectList):
    # FCFS
    start = 0
    FCFSList = []
    for project in projectList:
        if start < project.arriveTime:
            start = project.arriveTime
            project.start = start
            start += project.workTime
        else:
            project.start = start
            start += project.workTime
        FCFSList.append(project)
    return FCFSList


def SJF(projectList):
    resList = []

    # 先找到第一个到达的
    resList.append(projectList.pop(0))
    while projectList:
        index = 0
        front = resList[-1]
        # 当前一列表的最后的结束时，后一列表的第一个进程还没有到达，则后一列表的第一个进程放到前面
        if front.workTime + front.start < projectList[0].arriveTime:
            front = projectList.pop(0)
            resList.append(front)
            # projectList = projectList[1:]  # 把其余的单列出来

            # 找到列表中其余进程 在front执行结束前到达的所有进程， 放在temp列表中进行处理
        for project in projectList:
            if project.arriveTime <= front.start + front.workTime:
                index += 1
            else:
                break
        temp = projectList[0: index]
        # print('temp',temp)
        projectList = projectList[index:]
        # print('projectList2', projectList)
        temp.sort(key=lambda project: project.workTime)
        resList.extend(temp)
        resList = FCFS(resList)
        # print("resList", resList)
        # print("-"*40)
    return resList


def HRR(projectList):
    resList = []

    # 先找到第一个到达的
    resList.append(projectList.pop(0))
    while projectList:
        index = 0
        front = resList[-1]
        # 当前一列表的最后的结束时，后一列表的第一个进程还没有到达，则后一列表的第一个进程放到前面
        if front.workTime + front.start < projectList[0].arriveTime:
            front = projectList.pop(0)
            resList.append(front)
            # projectList = projectList[1:]  # 把其余的单列出来

            # 找到列表中其余进程 在front执行结束前到达的所有进程， 放在temp列表中进行处理
        for project in projectList:
            if project.arriveTime <= front.start + front.workTime:
                index += 1
            else:
                break
        temp = projectList[0: index]

        projectList = projectList[index:]

        temp.sort(key=lambda project: project.getResponseRatio(front.start + front.workTime), reverse=True)  # 高响应比优先 要做逆转
        resList.extend(temp)
        resList = FCFS(resList)
    return resList

#
# from copy import deepcopy
# projectList = init(4)
# copyList = deepcopy(projectList)
#
# print(List2Str(projectList, init=True))
#
# projectList = deepcopy(copyList)
# FCFSresult = FCFS(projectList)
# print(List2Str(FCFSresult), "平均周转时间+平均带权周转时间", getAvgRunTime(FCFSresult))
# print("-"*30)
#
# projectList = deepcopy(copyList)
# SJFresult = SJF(projectList)
# print(List2Str(SJFresult), "平均周转时间+平均带权周转时间", getAvgRunTime(SJFresult))
# print("-"*30)
#
# projectList = deepcopy(copyList)
# HRRresult = HRR(projectList)
# print(List2Str(HRRresult), "平均周转时间+平均带权周转时间", getAvgRunTime(HRRresult))
# print("-"*30)

